<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Mixed Precision Arithmetic</title>
<link rel="stylesheet" href="../../multiprecision.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter 1. Boost.Multiprecision">
<link rel="up" href="../tut.html" title="Tutorial">
<link rel="prev" href="rounding.html" title="Rounding Rules for Conversions">
<link rel="next" href="variable.html" title="Variable Precision Arithmetic">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="rounding.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="variable.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_multiprecision.tut.mixed"></a><a class="link" href="mixed.html" title="Mixed Precision Arithmetic">Mixed Precision Arithmetic</a>
</h3></div></div></div>
<p>
        Mixed precision arithmetic is fully supported by the library.
      </p>
<p>
        There are three different forms:
      </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
            Where the operands are of different precision or types.
          </li>
<li class="listitem">
            Where the operands are of the same type and precision, but yield a higher
            precision result.
          </li>
<li class="listitem">
            Where the operands or result are different but equivalent types (for
            example types which differ only in their memory management).
          </li>
</ul></div>
<h5>
<a name="boost_multiprecision.tut.mixed.h0"></a>
        <span class="phrase"><a name="boost_multiprecision.tut.mixed.mixing_operands_of_differing_typ"></a></span><a class="link" href="mixed.html#boost_multiprecision.tut.mixed.mixing_operands_of_differing_typ">Mixing
        Operands of Differing Types or Precision</a>
      </h5>
<p>
        If the arguments to a binary operator are of different types or precision,
        then the operation is allowed as long as there is an unambiguous implicit
        conversion from one argument type to the other. In all cases the arithmetic
        is performed "as if" the lower precision type is promoted to the
        higher precision type before applying the operator. However, particular backends
        may optimise this and avoid actually creating a temporary if they are able
        to do so.
      </p>
<p>
        For example:
      </p>
<pre class="programlisting"><span class="identifier">mpfr_float_50</span>         <span class="identifier">a</span><span class="special">(</span><span class="number">2</span><span class="special">),</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">mpfr_float_100</span>        <span class="identifier">c</span><span class="special">(</span><span class="number">3</span><span class="special">),</span> <span class="identifier">d</span><span class="special">;</span>
<span class="identifier">static_mpfr_float_50</span>  <span class="identifier">e</span><span class="special">(</span><span class="number">5</span><span class="special">),</span> <span class="identifier">f</span><span class="special">;</span>
<span class="identifier">mpz_int</span>               <span class="identifier">i</span><span class="special">(</span><span class="number">20</span><span class="special">);</span>

<span class="identifier">d</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">c</span><span class="special">;</span>  <span class="comment">// OK, result of operand is an mpfr_float_100.</span>
<span class="identifier">b</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">c</span><span class="special">;</span>  <span class="comment">// Error, can't convert the result to an mpfr_float_50 as it will lose digits.</span>
<span class="identifier">f</span> <span class="special">=</span> <span class="identifier">e</span> <span class="special">*</span> <span class="identifier">i</span><span class="special">;</span>  <span class="comment">// OK, unambiguous conversion from mpz_int to static_mpfr_float_50</span>
</pre>
<h5>
<a name="boost_multiprecision.tut.mixed.h1"></a>
        <span class="phrase"><a name="boost_multiprecision.tut.mixed.operands_of_the_same_precision"></a></span><a class="link" href="mixed.html#boost_multiprecision.tut.mixed.operands_of_the_same_precision">Operands
        of the Same Precision</a>
      </h5>
<p>
        Sometimes you want to apply an operator to two arguments of the same precision
        in such a way as to obtain a result of higher precision. The most common
        situation occurs with fixed precision integers, where you want to multiply
        two N-bit numbers to obtain a 2N-bit result. This is supported in this library
        by the following free functions:
      </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">ResultType</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Source1</span> <span class="keyword">class</span> <span class="identifier">Source2</span><span class="special">&gt;</span>
<span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">result</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source1</span><span class="special">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source2</span><span class="special">&amp;</span> <span class="identifier">b</span><span class="special">);</span>

<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">ResultType</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Source1</span> <span class="keyword">class</span> <span class="identifier">Source2</span><span class="special">&gt;</span>
<span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">subtract</span><span class="special">(</span><span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">result</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source1</span><span class="special">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source2</span><span class="special">&amp;</span> <span class="identifier">b</span><span class="special">);</span>

<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">ResultType</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Source1</span> <span class="keyword">class</span> <span class="identifier">Source2</span><span class="special">&gt;</span>
<span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">multiply</span><span class="special">(</span><span class="identifier">ResultType</span><span class="special">&amp;</span> <span class="identifier">result</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source1</span><span class="special">&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">Source2</span><span class="special">&amp;</span> <span class="identifier">b</span><span class="special">);</span>
</pre>
<p>
        These functions apply the named operator to the arguments <span class="emphasis"><em>a</em></span>
        and <span class="emphasis"><em>b</em></span> and store the result in <span class="emphasis"><em>result</em></span>,
        returning <span class="emphasis"><em>result</em></span>. In all cases they behave "as
        if" arguments <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> were
        first promoted to type <code class="computeroutput"><span class="identifier">ResultType</span></code>
        before applying the operator, though particular backends may well avoid that
        step by way of an optimization.
      </p>
<p>
        The type <code class="computeroutput"><span class="identifier">ResultType</span></code> must
        be an instance of class <code class="computeroutput"><span class="identifier">number</span></code>,
        and the types <code class="computeroutput"><span class="identifier">Source1</span></code> and
        <code class="computeroutput"><span class="identifier">Source2</span></code> may be either instances
        of class <code class="computeroutput"><span class="identifier">number</span></code> or native
        integer types. The latter is an optimization that allows arithmetic to be
        performed on native integer types producing an extended precision result.
      </p>
<p>
        For example:
      </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multiprecision</span><span class="special">/</span><span class="identifier">cpp_int</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
   <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">;</span>

   <span class="identifier">std</span><span class="special">::</span><span class="identifier">uint64_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">uint64_t</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">)();</span>
   <span class="identifier">std</span><span class="special">::</span><span class="identifier">uint64_t</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>

   <span class="identifier">uint128_t</span> <span class="identifier">ui128</span><span class="special">;</span>
   <span class="identifier">uint256_t</span> <span class="identifier">ui256</span><span class="special">;</span>
   <span class="comment">//</span>
   <span class="comment">// Start by performing arithmetic on 64-bit integers to yield 128-bit results:</span>
   <span class="comment">//</span>
   <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">showbase</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
   <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">showbase</span> <span class="special">&lt;&lt;</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">ui128</span><span class="special">,</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
   <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">showbase</span> <span class="special">&lt;&lt;</span> <span class="identifier">multiply</span><span class="special">(</span><span class="identifier">ui128</span><span class="special">,</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
   <span class="comment">//</span>
   <span class="comment">// The try squaring a 128-bit integer to yield a 256-bit result:</span>
   <span class="comment">//</span>
   <span class="identifier">ui128</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special">&lt;</span><span class="identifier">uint128_t</span><span class="special">&gt;::</span><span class="identifier">max</span><span class="special">)();</span>
   <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">hex</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">showbase</span> <span class="special">&lt;&lt;</span> <span class="identifier">multiply</span><span class="special">(</span><span class="identifier">ui256</span><span class="special">,</span> <span class="identifier">ui128</span><span class="special">,</span> <span class="identifier">ui128</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>

   <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
        Produces the output:
      </p>
<pre class="programlisting"><span class="number">0</span><span class="identifier">xffffffffffffffff</span>
<span class="number">0</span><span class="identifier">x10000000000000000</span>
<span class="number">0</span><span class="identifier">xFFFFFFFFFFFFFFFE0000000000000001</span>
<span class="number">0</span><span class="identifier">xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000001</span>
</pre>
<h5>
<a name="boost_multiprecision.tut.mixed.h2"></a>
        <span class="phrase"><a name="boost_multiprecision.tut.mixed.mixing_different_but_equivalent_"></a></span><a class="link" href="mixed.html#boost_multiprecision.tut.mixed.mixing_different_but_equivalent_">Mixing
        different, but "equivalent" types</a>
      </h5>
<p>
        Ordinarily, mixing types of the same precision will produce a compiler error
        since there is no unambiguous result type. However, there is a traits class:
      </p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">multiprecision</span>

<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">NumberType1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">NumberType2</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_equivalent_number_type</span><span class="special">;</span>

<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
        When it's <code class="computeroutput"><span class="identifier">value</span></code> const-member
        value is <code class="computeroutput"><span class="keyword">true</span></code> then the library
        will treat the types <code class="computeroutput"><span class="identifier">NumberType1</span></code>
        and <code class="computeroutput"><span class="identifier">NumberType2</span></code> as if they
        are interchangeable. This is typically used to optimise memory management
        by using two types with differing memory allocation strategies for different
        roles. Typically, we would be using a type with dymanic memory allocation
        and a minimal memory footprint for the main storage type (think large arrays
        or matrices), but a type with internal storage and no dynamic allocation
        (but a larger memory footprint) for a few select calculations.
      </p>
<p>
        There are three backends that define this trait by default:
      </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
            <a class="link" href="ints/cpp_int.html" title="cpp_int">cpp_int</a>'s,
            provided the two types differ only in their internal cache size.
          </li>
<li class="listitem">
            <a class="link" href="floats/cpp_bin_float.html" title="cpp_bin_float">cpp_bin_float</a>'s
            provided they are of the same precision.
          </li>
<li class="listitem">
            <a class="link" href="floats/mpfr_float.html" title="mpfr_float">mpfr_float</a>'s
            provided they are of the same precision.
          </li>
</ul></div>
<p>
        In addition, while this feature can be used with expression templates turned
        off, this feature minimises temporaries and hence memory allocations when
        expression template are turned on.
      </p>
<p>
        By way of an example, consider the dot product of two vectors of <a class="link" href="ints/cpp_int.html" title="cpp_int">cpp_int</a>'s,
        our first, fairly trivial implementation might look like this:
      </p>
<pre class="programlisting"><span class="identifier">cpp_int</span> <span class="identifier">dot_product_1</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v1</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v2</span><span class="special">)</span>
<span class="special">{</span>
   <span class="keyword">if</span> <span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">!=</span> <span class="identifier">v2</span><span class="special">.</span><span class="identifier">size</span><span class="special">())</span>
      <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">(</span><span class="string">"Mismatched arguments"</span><span class="special">);</span>

   <span class="identifier">cpp_int</span> <span class="identifier">result</span><span class="special">;</span>
   <span class="keyword">for</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
      <span class="identifier">result</span> <span class="special">+=</span> <span class="identifier">v1</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">*</span> <span class="identifier">v2</span><span class="special">[</span><span class="identifier">i</span><span class="special">];</span>
   <span class="comment">//</span>
   <span class="comment">// Named-return value optimisation (even better than a move):</span>
   <span class="comment">//</span>
   <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
        However, in order to reduce the need for memory allocations when constructing
        the temporaries needed for the multiply-and-add operations, we could use
        an equivalent type with a larger internal cache like this:
      </p>
<pre class="programlisting"><span class="identifier">cpp_int</span> <span class="identifier">dot_product_2</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v1</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v2</span><span class="special">)</span>
<span class="special">{</span>
   <span class="keyword">if</span> <span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">!=</span> <span class="identifier">v2</span><span class="special">.</span><span class="identifier">size</span><span class="special">())</span>
      <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">(</span><span class="string">"Mismatched arguments"</span><span class="special">);</span>
   <span class="comment">//</span>
   <span class="comment">// If we know that most of our data is of a certain range of values, then we can use a cpp_int type</span>
   <span class="comment">// with an internal cache large enough to *probably* not require an allocation:</span>
   <span class="comment">//</span>
   <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">cpp_int_backend</span><span class="special">&lt;</span><span class="number">1024</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">result</span><span class="special">;</span>
   <span class="keyword">for</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
      <span class="identifier">result</span> <span class="special">+=</span> <span class="identifier">v1</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">*</span> <span class="identifier">v2</span><span class="special">[</span><span class="identifier">i</span><span class="special">];</span>
   <span class="comment">//</span>
   <span class="comment">// We can't rely on the named-return-value optimisation here, since the variable being returned</span>
   <span class="comment">// is a different type to the return value.  However, since these are "equivalent" types we</span>
   <span class="comment">// can move the result to the return value and get all the expected move-optimisations should</span>
   <span class="comment">// variable result have dynamically allocated:</span>
   <span class="comment">//</span>
   <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">result</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
        Before we compare performance though, there is one other obvious thing we
        could try. By simply declaring a variable for the result of the intermediate
        multiplications, and reusing that variable each time through the loop, we
        might also expect to greatly reduce the number of allocations required.
      </p>
<pre class="programlisting"><span class="identifier">cpp_int</span> <span class="identifier">dot_product_3</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v1</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">cpp_int</span><span class="special">&gt;&amp;</span> <span class="identifier">v2</span><span class="special">)</span>
<span class="special">{</span>
   <span class="keyword">if</span> <span class="special">(</span><span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">!=</span> <span class="identifier">v2</span><span class="special">.</span><span class="identifier">size</span><span class="special">())</span>
      <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">(</span><span class="string">"Mismatched arguments"</span><span class="special">);</span>

   <span class="identifier">cpp_int</span> <span class="identifier">result</span><span class="special">,</span> <span class="identifier">term</span><span class="special">;</span>
   <span class="keyword">for</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">v1</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
   <span class="special">{</span>
      <span class="comment">//</span>
      <span class="comment">// Re-use the same variable for the result of the multiplications, rather than rely on </span>
      <span class="comment">// an internally generated temporary.  Depending on the input data, this may allocate</span>
      <span class="comment">// a few times depending how soon in the input vector's we encounter the largest values.</span>
      <span class="comment">// In the best case though, or for fairly uniformly sized input data, we will allocate </span>
      <span class="comment">// only once:</span>
      <span class="comment">//</span>
      <span class="identifier">term</span> <span class="special">=</span> <span class="identifier">v1</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">*</span> <span class="identifier">v2</span><span class="special">[</span><span class="identifier">i</span><span class="special">];</span>
      <span class="identifier">result</span> <span class="special">+=</span> <span class="identifier">term</span><span class="special">;</span>
   <span class="special">}</span>
   <span class="comment">//</span>
   <span class="comment">// Named-return value optimisation (even better than a move):</span>
   <span class="comment">//</span>
   <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
        We'll begin by comparing how many actual allocations were required to calculate
        the dot product of 1000 value vectors for random data with various bit counts:
      </p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                <p>
                  Bit Count
                </p>
              </th>
<th>
                <p>
                  Allocations Count Version 1
                </p>
              </th>
<th>
                <p>
                  Allocations Count Version 2
                </p>
              </th>
<th>
                <p>
                  Allocations Count Version 3
                </p>
              </th>
</tr></thead>
<tbody>
<tr>
<td>
                <p>
                  32
                </p>
              </td>
<td>
                <p>
                  1<a href="#ftn.boost_multiprecision.tut.mixed.f0" class="footnote" name="boost_multiprecision.tut.mixed.f0"><sup class="footnote">[1]</sup></a>
                </p>
              </td>
<td>
                <p>
                  0
                </p>
              </td>
<td>
                <p>
                  0
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  64
                </p>
              </td>
<td>
                <p>
                  1001
                </p>
              </td>
<td>
                <p>
                  1<a href="#ftn.boost_multiprecision.tut.mixed.f1" class="footnote" name="boost_multiprecision.tut.mixed.f1"><sup class="footnote">[2]</sup></a>
                </p>
              </td>
<td>
                <p>
                  1
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  128
                </p>
              </td>
<td>
                <p>
                  1002
                </p>
              </td>
<td>
                <p>
                  1
                </p>
              </td>
<td>
                <p>
                  2
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  256
                </p>
              </td>
<td>
                <p>
                  1002
                </p>
              </td>
<td>
                <p>
                  1
                </p>
              </td>
<td>
                <p>
                  3<a href="#ftn.boost_multiprecision.tut.mixed.f2" class="footnote" name="boost_multiprecision.tut.mixed.f2"><sup class="footnote">[3]</sup></a>
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  512
                </p>
              </td>
<td>
                <p>
                  1002
                </p>
              </td>
<td>
                <p>
                  1
                </p>
              </td>
<td>
                <p>
                  3
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  1024
                </p>
              </td>
<td>
                <p>
                  1002
                </p>
              </td>
<td>
                <p>
                  1001<a href="#ftn.boost_multiprecision.tut.mixed.f3" class="footnote" name="boost_multiprecision.tut.mixed.f3"><sup class="footnote">[4]</sup></a>
                </p>
              </td>
<td>
                <p>
                  3
                </p>
              </td>
</tr>
</tbody>
<tbody class="footnotes"><tr><td colspan="4">
<div id="ftn.boost_multiprecision.tut.mixed.f0" class="footnote"><p><a href="#boost_multiprecision.tut.mixed.f0" class="para"><sup class="para">[1] </sup></a>
                    Here everything fits within <a class="link" href="ints/cpp_int.html" title="cpp_int">cpp_int</a>'s
                    default internal cache, so no allocation are required.
                  </p></div>
<div id="ftn.boost_multiprecision.tut.mixed.f1" class="footnote"><p><a href="#boost_multiprecision.tut.mixed.f1" class="para"><sup class="para">[2] </sup></a>
                    A single allocation for the return value.
                  </p></div>
<div id="ftn.boost_multiprecision.tut.mixed.f2" class="footnote"><p><a href="#boost_multiprecision.tut.mixed.f2" class="para"><sup class="para">[3] </sup></a>
                    Here the input data is such that more than one allocation is
                    required for the temporary.
                  </p></div>
<div id="ftn.boost_multiprecision.tut.mixed.f3" class="footnote"><p><a href="#boost_multiprecision.tut.mixed.f3" class="para"><sup class="para">[4] </sup></a>
                    At this point we exceed the internal cache of our internal calculation
                    type.
                  </p></div>
</td></tr></tbody>
</table></div>
<p>
        Timings for the three methods are as follows (MSVC-16.8.0, x64):
      </p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                <p>
                  Bit Count
                </p>
              </th>
<th>
                <p>
                  time/ms Version 1
                </p>
              </th>
<th>
                <p>
                  time/ms Version 2
                </p>
              </th>
<th>
                <p>
                  time/ms Version 3
                </p>
              </th>
</tr></thead>
<tbody>
<tr>
<td>
                <p>
                  32
                </p>
              </td>
<td>
                <p>
                  0.021
                </p>
              </td>
<td>
                <p>
                  0.021
                </p>
              </td>
<td>
                <p>
                  0.021
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  64
                </p>
              </td>
<td>
                <p>
                  0.032
                </p>
              </td>
<td>
                <p>
                  0.032
                </p>
              </td>
<td>
                <p>
                  0.029
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  128
                </p>
              </td>
<td>
                <p>
                  0.099
                </p>
              </td>
<td>
                <p>
                  0.041
                </p>
              </td>
<td>
                <p>
                  0.041
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  256
                </p>
              </td>
<td>
                <p>
                  0.154
                </p>
              </td>
<td>
                <p>
                  0.091
                </p>
              </td>
<td>
                <p>
                  0.094
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  512
                </p>
              </td>
<td>
                <p>
                  0.323
                </p>
              </td>
<td>
                <p>
                  0.270
                </p>
              </td>
<td>
                <p>
                  0.269
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  1024
                </p>
              </td>
<td>
                <p>
                  0.998
                </p>
              </td>
<td>
                <p>
                  0.995
                </p>
              </td>
<td>
                <p>
                  0.949
                </p>
              </td>
</tr>
</tbody>
</table></div>
<p>
        As you can see, there is a sweet spot for middling-sized integers where we
        gain: if the values are small, then <a class="link" href="ints/cpp_int.html" title="cpp_int">cpp_int</a>'s
        own internal cache is large enough anyway, and no allocation occur. Conversely,
        if the values are sufficiently large, then the cost of the actual arithmetic
        dwarfs the memory allocation time. In this particular case, carefully writing
        the code (version 3) is clearly at least as good as using a separate type
        with a larger cache. However, there may be times when it's not practical
        to re-write existing code, purely to optimise it for the multiprecision use
        case.
      </p>
<p>
        A typical example where we can't rewrite our code to avoid unnecessary allocations,
        occurs when we're calling an external routine. For example the arc length
        of an ellipse with radii <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span>
        is given by:
      </p>
<pre class="programlisting">L(a, b) = 4aE(k)</pre>
<p>
        with:
      </p>
<pre class="programlisting">k = √(1 - b<sup>2</sup>/a<sup>2</sup>)</pre>
<p>
        where <span class="emphasis"><em>E(k)</em></span> is the complete elliptic integral of the
        second kind, which is available as a template function <code class="computeroutput"><span class="identifier">ellint_2</span></code>
        in Boost.Math.
      </p>
<p>
        Naively, we might implement this for use with <a class="link" href="floats/mpfr_float.html" title="mpfr_float">mpfr_float</a>
        like this:
      </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="identifier">N</span><span class="special">&gt;</span>
<span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">elliptic_arc_length_1</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;&amp;</span> <span class="identifier">b</span><span class="special">)</span>
<span class="special">{</span>
   <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="number">1</span> <span class="special">-</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">b</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">a</span><span class="special">));</span>
   <span class="keyword">return</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">ellint_2</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
        But we might also try mixing our arithmetic types - regular dynamically allocated
        <a class="link" href="floats/mpfr_float.html" title="mpfr_float">mpfr_float</a>'s
        for the interface to minimise memory footprint in our external storage, and
        statically allocated <a class="link" href="floats/mpfr_float.html" title="mpfr_float">mpfr_float</a>'s
        for the internal arithmetic:
      </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">unsigned</span> <span class="identifier">N</span><span class="special">&gt;</span>
<span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">elliptic_arc_length_2</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;&amp;</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;</span> <span class="special">&gt;&amp;</span> <span class="identifier">b</span><span class="special">)</span>
<span class="special">{</span>
   <span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">,</span> <span class="identifier">allocate_stack</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="number">1</span> <span class="special">-</span> <span class="identifier">b</span> <span class="special">*</span> <span class="identifier">b</span> <span class="special">/</span> <span class="special">(</span><span class="identifier">a</span> <span class="special">*</span> <span class="identifier">a</span><span class="special">));</span>
   <span class="keyword">return</span> <span class="number">4</span> <span class="special">*</span> <span class="identifier">a</span> <span class="special">*</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">ellint_2</span><span class="special">(</span><span class="identifier">k</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
        The performance comparisons are surprisingly stark:
      </p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                <p>
                  N
                </p>
              </th>
<th>
                <p>
                  <code class="computeroutput"><span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">&gt;&gt;</span></code>
                  / ms
                </p>
              </th>
<th>
                <p>
                  <code class="computeroutput"><span class="identifier">number</span><span class="special">&lt;</span><span class="identifier">mpfr_float_backend</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">,</span>
                  <span class="identifier">allocate_stack</span><span class="special">&gt;&gt;</span></code>
                  / ms
                </p>
              </th>
</tr></thead>
<tbody>
<tr>
<td>
                <p>
                  30
                </p>
              </td>
<td>
                <p>
                  19.5
                </p>
              </td>
<td>
                <p>
                  3.1
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  40
                </p>
              </td>
<td>
                <p>
                  12.5
                </p>
              </td>
<td>
                <p>
                  6.2
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  50
                </p>
              </td>
<td>
                <p>
                  14.4
                </p>
              </td>
<td>
                <p>
                  6.6
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  60
                </p>
              </td>
<td>
                <p>
                  18.0
                </p>
              </td>
<td>
                <p>
                  9.5
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  70
                </p>
              </td>
<td>
                <p>
                  18.0
                </p>
              </td>
<td>
                <p>
                  9.6
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  80
                </p>
              </td>
<td>
                <p>
                  20.0
                </p>
              </td>
<td>
                <p>
                  12.8
                </p>
              </td>
</tr>
</tbody>
</table></div>
<p>
        As before, the results are for MSVC-16.8.0/x64, and in point of fact, the
        results do not always favour non-allocating types so much, it does depend
        very much on the special function being called and/or the arguments used.
      </p>
<h5>
<a name="boost_multiprecision.tut.mixed.h3"></a>
        <span class="phrase"><a name="boost_multiprecision.tut.mixed.backends_with_optimized_mixed_pr"></a></span><a class="link" href="mixed.html#boost_multiprecision.tut.mixed.backends_with_optimized_mixed_pr">Backends
        With Optimized Mixed Precision Arithmetic</a>
      </h5>
<p>
        The following backends have at least some direct support for mixed-precision
        arithmetic, and therefore avoid creating unnecessary temporaries when using
        the interfaces above. Therefore when using these types it's more efficient
        to use mixed-precision arithmetic, than it is to explicitly cast the operands
        to the result type:
      </p>
<p>
        <a class="link" href="floats/mpfr_float.html" title="mpfr_float">mpfr_float</a>,
        <a class="link" href="floats/gmp_float.html" title="gmp_float">gmp_float</a>,
        <a class="link" href="ints/cpp_int.html" title="cpp_int">cpp_int</a>.
      </p>
</div>
<div class="copyright-footer">Copyright © 2002-2020 John
      Maddock and Christopher Kormanyos<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="rounding.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="variable.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
